package xyz.csmcool.imchat.service.impl;

import com.alibaba.fastjson.JSON;
import jdk.nashorn.internal.runtime.JSONFunctions;
import lombok.RequiredArgsConstructor;
import org.springframework.web.multipart.MultipartFile;
import xyz.csmcool.imchat.constants.Filetype;
import xyz.csmcool.imchat.entity.FileInfo;
import xyz.csmcool.imchat.entity.FileMessageVo;
import xyz.csmcool.imchat.entity.RoomsChats;
import xyz.csmcool.imchat.entity.vo.RoomChatsVo;
import xyz.csmcool.imchat.feignclient.OssClint;
import xyz.csmcool.imchat.feignclient.RoomClient;
import xyz.csmcool.imchat.feignclient.UserClient;
import xyz.csmcool.imchat.mapper.RoomsChatsMapper;
import xyz.csmcool.imchat.service.IRoomsChatsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import xyz.csmcool.imchat.service.RabbitmqService;
import xyz.csmcool.imutil.ExceptionHandler.CommonException;
import xyz.csmcool.imutil.dto.LastMessageDto;
import xyz.csmcool.imutil.dto.Message;
import xyz.csmcool.imutil.dto.UserDto;
import xyz.csmcool.imutil.utils.BeanUtil;
import xyz.csmcool.imutil.webVo.MyPage;
import xyz.csmcool.imutil.webVo.RedisService;
import xyz.csmcool.imutil.webVo.ResultCode;
import xyz.csmcool.imutil.webVo.ResultVo;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author csmcool
 * @since 2022-08-14
 */
@Service
@RequiredArgsConstructor
public class RoomsChatsServiceImpl extends ServiceImpl<RoomsChatsMapper, RoomsChats> implements IRoomsChatsService {

    final RedisService redisService;
    final RabbitmqService rabbitmqService;
    final UserClient userClient;
    final OssClint ossClint;
    final RoomsChatsMapper roomsChatsMapper;
    final RoomClient roomClient;

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");

    @Override
    public Message<String> sendMessage(Message<String> message, String uid) {
        checkedUserMuted(message.getRoomId(),Integer.valueOf(uid));
        getUseInfo(message, uid);
        message.setType(1);


        // 需要roomID本人是否加入
        RoomsChats roomsChats = new RoomsChats();
        BeanUtil.updateProperties(message, roomsChats);
        roomsChats.setMessage(message.getMessage());

        boolean save = save(roomsChats);
        if (save) {
            rabbitmqService.sendMessage(message, message.getRoomId());
        }

        return message;
    }

    @Override
    public void sendImageMessage(MultipartFile[] files, String uid, Integer roomId) {
        checkedUserMuted(roomId,Integer.valueOf(uid));
        Message<List> message = new Message<List>();
        getUseInfo(message, uid);
        message.setRoomId(roomId);
        message.setType(2);


        ResultVo<HashMap<String, List<String>>> hashMapResultVo = ossClint.uploadRoomFiles(files);
        if (!hashMapResultVo.getSucceed()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("发送信息失败"));
        }
        HashMap<String, List<String>> data = hashMapResultVo.getData();
        List<String> url = data.get("url");
        message.setMessage(url);

        //数据库存档
        RoomsChats roomsChats = new RoomsChats();
        BeanUtil.updateProperties(message, roomsChats);
        roomsChats.setMessage(JSON.toJSONString(url));

        //发送消息
        boolean save = save(roomsChats);
        if (save) {
            rabbitmqService.sendMessage(message, message.getRoomId());
        }
    }

    @Override
    public void sendSoundMessage(MultipartFile file, String uid, Integer roomId) {
        checkedUserMuted(roomId,Integer.valueOf(uid));
        Message<String> message = new Message<String>();
        getUseInfo(message, uid);
        message.setRoomId(roomId);
        message.setType(3);

        String fileUrl = getFileUrl(file);
        message.setMessage(fileUrl);

        //数据库存档
        RoomsChats roomsChats = new RoomsChats();
        BeanUtil.updateProperties(message, roomsChats);
        roomsChats.setMessage(fileUrl);

        //发送消息
        boolean save = save(roomsChats);
        if (save) {
            rabbitmqService.sendMessage(message, message.getRoomId());
        }
    }

    @Override
    public void sendFileMessage(MultipartFile file, String uid, Integer roomId) {
        checkedUserMuted(roomId,Integer.valueOf(uid));
        Message<FileInfo> message = new Message<>();
        getUseInfo(message, uid);
        message.setRoomId(roomId);
        message.setType(5);

        //封装数据
        FileInfo fileInfo = new FileInfo();
        String fileName = file.getOriginalFilename();
        long size = file.getSize();
        fileInfo.setName(fileName);
        fileInfo.setSize(size);
        fileInfo.setUrl(getFileUrl(file));

        message.setMessage(fileInfo);

        //数据库存档
        RoomsChats roomsChats = new RoomsChats();
        BeanUtil.updateProperties(message, roomsChats);
        roomsChats.setMessage(JSON.toJSONString(fileInfo));

        //发送消息
        boolean save = save(roomsChats);
        if (save) {
            rabbitmqService.sendMessage(message, message.getRoomId());
        }
    }

    @Override
    public void sendMp4Message(MultipartFile file, String uid, Integer roomId) {
        checkedUserMuted(roomId,Integer.valueOf(uid));
        Message<String> message = new Message<String>();
        getUseInfo(message, uid);
        message.setRoomId(roomId);
        message.setType(6);

        String fileUrl = getFileUrl(file);
        message.setMessage(fileUrl);

        //数据库存档
        RoomsChats roomsChats = new RoomsChats();
        BeanUtil.updateProperties(message, roomsChats);
        roomsChats.setMessage(fileUrl);

        //发送消息
        boolean save = save(roomsChats);
        if (save) {
            rabbitmqService.sendMessage(message, message.getRoomId());
        }
    }

    /**
     * send*
     *
     * @param fileMessageVo
     * @param uid
     */
    @Override
    public void sendRoomFileMessage(FileMessageVo fileMessageVo, String uid) {
        checkedUserMuted(fileMessageVo.getRoomId(),Integer.valueOf(uid));
        Message message = new Message<String>();
        getUseInfo(message, uid);
        message.setRoomId(fileMessageVo.getRoomId());

        // 获取文件后缀名
        String fileName = fileMessageVo.getFileName();
        String hou = fileName.substring(fileName.lastIndexOf("."));

        RoomsChats roomsChats = new RoomsChats();
        String fileUrl = getFileUrl(fileName, fileMessageVo.getUploadId());
        if (Filetype.MP3.getTypeName().equals(hou)) {
            message.setType(3);
            //获取文件地址
            message.setMessage(fileUrl);

            //数据库存档
            BeanUtil.updateProperties(message, roomsChats);
            roomsChats.setMessage(fileUrl);

        } else if (Filetype.IMAGE.getTypeName().equals(hou) || Filetype.PNG.getTypeName().equals(hou)) {
            message.setType(2);

            List<String> url = new LinkedList<>();
            url.add(fileUrl);
            message.setMessage(url);

            //数据库存档
            BeanUtil.updateProperties(message, roomsChats);
            roomsChats.setMessage(JSON.toJSONString(url));

        } else if (Filetype.MP4.getTypeName().equals(hou)) {
            message.setType(6);

            message.setMessage(fileUrl);
            BeanUtil.updateProperties(message, roomsChats);
            roomsChats.setMessage(fileUrl);

        } else {
            message.setType(5);
            //封装数据
            FileInfo fileInfo = new FileInfo();
            fileInfo.setName(fileMessageVo.getName());
            fileInfo.setSize(fileMessageVo.getSize());
            fileInfo.setUrl(fileUrl);
            message.setMessage(fileInfo);
            BeanUtil.updateProperties(message, roomsChats);
            roomsChats.setMessage(JSON.toJSONString(fileInfo));
        }

        //发送消息
        boolean save = save(roomsChats);
        if (save) {
            rabbitmqService.sendMessage(message, message.getRoomId());
        }
    }

    /**
     * 获取每个房间的最后一条信息*
     *
     * @param ids
     * @return
     */
    @Override
    public List<LastMessageDto> getLastMessage(List<Integer> ids) {
        List<LastMessageDto> lastMessage = roomsChatsMapper.getLastMessage(ids);
        return lastMessage;
    }

    /**
     * 第一次获取历史消息记录
     *
     * @param roomId
     * @return
     */
    @Override
    public List<RoomChatsVo> getFirstHistory(Integer roomId,Integer uid) {
        checkedUser(roomId,uid);
        List<RoomsChats> roomsChats = roomsChatsMapper.selectFirstHistoryChat(roomId);
        return getMessageByHistory(roomsChats);
    }

    /**
     * 查看历史消息
     *
     * @param page
     * @param limit
     * @param roomId
     * @param id
     * @return
     */
    @Override
    public MyPage<RoomChatsVo> getHistoryMessage(Long page, Long limit, Integer roomId, Integer id,Integer uid) {
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;

        //检车是否为该聊天室用户
        checkedUser(roomId,uid);

        List<RoomsChats> roomsChats = roomsChatsMapper.selectHistoryChat(page, limit, roomId, id);
        MyPage<RoomChatsVo> myPage = new MyPage<>();
        List<RoomChatsVo> messageByHistory = getMessageByHistory(roomsChats);
        myPage.setContent(messageByHistory);
        myPage.setTotalElements(roomsChatsMapper.selectHistoryChatsCount(roomId));
        return myPage;
    }

    /**
     * 查看历史图片
     *
     * @param page
     * @param limit
     * @param roomId
     * @param id
     * @return
     */
    @Override
    public MyPage<String> getHistoryImg(Long page, Long limit, Integer roomId, Integer id) {
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;
        //判断用户是否是聊天室用户;
        checkedUser(roomId,id);

        List<String> strings = roomsChatsMapper.selectHistoryImg(page, limit, roomId);
        MyPage<String> myPage = new MyPage<>();
        myPage.setContent(strings);
        myPage.setTotalElements(roomsChatsMapper.selectHistoryCount(roomId, 2));
        return myPage;
    }

    /**
     * 查看历史文件
     *
     * @param page
     * @param limit
     * @param roomId
     * @param id
     * @return
     */
    @Override
    public MyPage<String> getHistoryFile(Long page, Long limit, Integer roomId, Integer id) {
        limit = limit < 1 ? 10 : limit;
        page = page < 1 ? 0 : (page - 1) * limit;
        //判断用户是否是聊天室用户;
        checkedUser(roomId,id);

        List<String> strings = roomsChatsMapper.selectHistoryFile(page, limit, roomId);
        MyPage<String> myPage = new MyPage<>();
        myPage.setContent(strings);
        myPage.setTotalElements(roomsChatsMapper.selectHistoryCount(roomId, 6));
        return myPage;
    }

    /**
     * 删除聊天记录*
     *
     * @param roomId
     * @return
     */
    @Override
    public Boolean deleteRoomChats(Integer roomId) {
        return roomsChatsMapper.deleteRoomChats(roomId);
    }

    /**
     * 清空聊天室
     *
     * @param roomId
     * @param uid
     * @return
     */
    @Override
    public void clearRoomChats(Integer roomId, Integer uid) {
        ResultVo myRoom = roomClient.isMyRoom(roomId, uid);
        if(myRoom.getSucceed()) {
            Boolean aBoolean = roomsChatsMapper.deleteRoomChats(roomId);
            if(!aBoolean) {
                throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("删除聊天信息失败"));
            }
        }
    }


    public void getUseInfo(Message message, String uid) {
        message.setSenderId(Integer.valueOf(uid));
        ResultVo<UserDto> userInfo = userClient.getUserInfo(uid);
        if (!userInfo.getSucceed()) {
            System.err.println("出现异常");
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("发送信息失败"));
        }
        UserDto users = userInfo.getData();
        message.setSenderName(users.getUserName());
        message.setSenderAvatar(users.getAvatar());
        message.setCreateTime(new Date());
    }

    public String getFileUrl(MultipartFile file) {
        ResultVo<HashMap<String, String>> hashMapResultVo = ossClint.uploadRoomFile(file);
        if (!hashMapResultVo.getSucceed()) {
            System.err.println("出现异常");
            System.out.println(hashMapResultVo.getmessage());
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("发送文件失败"));
        }
        HashMap<String, String> data = hashMapResultVo.getData();
        String url = data.get("url");
        return url;
    }

    public String getFileUrl(String fileName, String uploadId) {
        ResultVo<HashMap<String, String>> hashMapResultVo = ossClint.completeMultipartUpload(fileName, uploadId);
        if (!hashMapResultVo.getSucceed()) {
            System.err.println("出现异常");
            System.out.println(hashMapResultVo.getmessage());
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("发送文件失败"));
        }
        Map<String, String> data = hashMapResultVo.getData();
        return data.get("url");
    }

    public List<RoomChatsVo> getMessageByHistory(List<RoomsChats> roomsChats) {
        List<Integer> uids = roomsChats.stream().map(RoomsChats::getSenderId).collect(Collectors.toList());
        ResultVo<List<UserDto>> roomUserInfo = userClient.getRoomUserInfo(uids);
        if (!roomUserInfo.getSucceed()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("获取消息失败"));
        }
        List<UserDto> data = roomUserInfo.getData();
        Map<Integer, String> userNames = data.stream().collect(
                Collectors.toMap(UserDto::getId, UserDto::getUserName));
        Map<Integer, String> avatars = data.stream().collect(
                Collectors.toMap(UserDto::getId, UserDto::getAvatar));

        List<RoomChatsVo> result = new LinkedList<>();
        for (RoomsChats roomsChat : roomsChats) {
            RoomChatsVo roomChatsVo = new RoomChatsVo();
            BeanUtil.updateProperties(roomsChat, roomChatsVo);
            roomChatsVo.setAvatar(avatars.get(roomsChat.getSenderId()));
            roomChatsVo.setUserName(userNames.get(roomsChat.getSenderId()));
            result.add(roomChatsVo);
        }
        return result;
    }

    public void checkedUser(Integer roomId, Integer id) {
        ResultVo<Map<String, Integer>> roomUser = roomClient.isRoomUser(roomId, id);
        if (!roomUser.getSucceed()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("获取历史聊天出了点问题"));
        }

        Map<String, Integer> data = roomUser.getData();
        if (data.get("result") == -1) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("该用户非当前聊天室成员").setCode(90242));
        }
    }

    public void checkedUserMuted(Integer roomId, Integer id) {
        ResultVo<Map<String, Integer>> roomUser = roomClient.isRoomUser(roomId, id);
        if (!roomUser.getSucceed()) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("获取历史聊天出了点问题"));
        }

        Map<String, Integer> data = roomUser.getData();
        Integer result = data.get("result");
        if (result == -1 || result == 1) {
            throw new CommonException(ResultCode.CUSTOM_FAIL.setMessage("你被禁言了，请找群主解封。").setCode(90241));
        }
    }
}
